home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 022 / pemacs / word.c < prev   
C/C++ Source or Header  |  1995-03-17  |  14KB  |  475 lines

  1. /*
  2.  * The routines in this file implement commands that work word at a time.
  3.  * There are all sorts of word mode commands. If I do any sentence and/or
  4.  * paragraph mode commands, they are likely to be put in this file.
  5.  */
  6.  
  7. #include        <stdio.h>
  8. #include        "ed.h"
  9.  
  10. #define WPNULL -1 /* null word pointer */
  11.  
  12. /* Paragraph fill.  Retain indenting of first line of paragraph.  Remove
  13.  * leading spaces from other lines.  Remove extra space between words.
  14.  * Fill each line to fillcol, breaking at word boundaries.
  15.  * Delete trailing space from all lines.  
  16.  */
  17. parafill( f, n)
  18. {
  19.     register int c; /* current char */
  20.     register short spo; /* space offset */
  21.     register short count;
  22.     short wo; /* word offset */
  23.     WINDOW *wp;
  24.     LINE *flp, /* first line of paragraph */
  25.      *clp; /* current line of paragraph */
  26.  
  27.     /* save old context */
  28.     /* we do this by creating a fake window which retains the context.
  29.      * this will be updated by the editing commands.
  30.      */
  31.         if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
  32.                 mlwrite("Cannot allocate WINDOW block");
  33.                 return (FALSE);
  34.         }
  35.         wp->w_bufp  = curbp;
  36.         wp->w_dotp  = curwp->w_dotp;
  37.         wp->w_doto  = curwp->w_doto;
  38.         wp->w_markp = curwp->w_markp;
  39.         wp->w_marko = curwp->w_marko;
  40.         wp->w_flag  = 0;
  41.         wp->w_force = 0;
  42.     wp->w_wndp = wheadp;
  43.     wheadp = wp;
  44.  
  45.     /* get first line of paragraph */
  46.  
  47.     for( flp = curwp->w_dotp; flp != curbp->b_linep; flp = lback( flp)) {
  48.         if( llength( flp) == 0) /* blank line, found it */
  49.         break;
  50.     }
  51.     flp = lforw( flp);
  52.     if( llength( flp) == 0) /* nothing to do */
  53.         return( TRUE);
  54.  
  55.     /* initialize */
  56.     count = 0;
  57.     curwp->w_dotp = clp = flp;
  58.  
  59.     for(;;) { /* go through all lines */
  60.     spo = count; /* set space offset at current spot */
  61.  
  62.     /* get to end of spaces */
  63.     for( ;; count++) {
  64.         c = wgetc( &clp, count);
  65.         if( (c != ' ') || (c == EOF)) break;
  66.     }
  67.     wo = count;
  68.  
  69.     /* get to end of word */
  70.     for( ;; count++) {
  71.         c = wgetc( &clp, count);
  72.         if( (c == ' ') || (c == EOF)) break;
  73.     }
  74.  
  75.     if(((clp != flp) || spo) && (spo != wo)) {
  76.     /* adjust spaces.  if at beginning of line, delete all spaces */
  77.         curwp->w_doto = spo;
  78.         if( spo) { /* past begin of line */
  79.         count += adjsp( &clp, spo, &wo);
  80.         } else { /* at begin of line */
  81.         ldelete( wo - spo, FALSE);
  82.         wo = count = 0;
  83.         }        
  84.     }
  85.  
  86.     if( count > fillcol) { /* if past fill column, break. */
  87.         if(((clp != flp) || spo) && (spo != wo)) {
  88.         /* collapse the spaces */
  89.         curwp->w_doto = spo;
  90.         ldelete( wo - spo, FALSE);
  91.         wo = spo;
  92.         }
  93.         if( wo > 0) { /* break at beginning of word */
  94.         curwp->w_doto = wo;
  95.         } else { /* break at end of word */
  96.         curwp->w_doto = count;
  97.         }
  98.         newline( FALSE, 1);
  99.         count = 0;
  100.         clp = curwp->w_dotp; /* updated by newline */
  101.     }
  102.     if( c == EOF) break;
  103.     }
  104.     /* restore context  and delete fake window */
  105.     curwp->w_dotp = wp->w_dotp;
  106.     curwp->w_doto = wp->w_doto;
  107.     curwp->w_markp = wp->w_markp;
  108.     curwp->w_marko = wp->w_marko;
  109.     wheadp = wp->w_wndp;
  110.     free( (char *) wp);
  111.  
  112.     return( TRUE);
  113. }
  114.  
  115. /* adjust the spacing between words.  check for colons and periods.
  116.  * assumes spo > 0 and doto is set to spo.
  117.  */
  118. adjsp( lp, spo, wo)
  119. register LINE **lp;
  120. register short spo, *wo;
  121. {
  122.     short result, spaces, n, c;
  123.  
  124.     /* decide on number of spaces */
  125.     switch( lgetc( *lp, spo -1)) {
  126.         case ':':
  127.         spaces = 2;
  128.         break;
  129.  
  130.         case '.':
  131.         spaces = 1; /* just a guess */
  132.         n = spo -2;
  133.         if( n == 0) /* period at beginning of line */
  134.             break;
  135.         else {
  136.             c = lgetc( *lp, n);
  137.             if((('a' <= c) && (c <= 'z'))
  138.             || (('A' <= c) && (c <= 'Z'))) { /* letter */
  139.             n -= 1;
  140.             if( n == 0) /* single letter followed by . */
  141.                 break;
  142.             else {
  143.                 c = lgetc( *lp, n);
  144.                 if((c == ' ')
  145.                 || (c == '.'))/* single letter followed by . */
  146.                 break;
  147.             }
  148.             } else /* not a letter */
  149.             break;
  150.         }
  151.         if( *wo < llength( *lp)) {
  152.             c = lgetc( *lp, *wo);
  153.             if((c < 'A') || ('Z' < c)) /* not a cap letter */
  154.             break;
  155.         }
  156.         spaces = 2;
  157.         break;
  158.  
  159.         default:
  160.         spaces = 1;
  161.         break;
  162.     }
  163.  
  164.     /* adjust them */
  165.     if( (*wo - spo) == spaces) /* perfect */
  166.         return( 0);
  167.     else if( (*wo - spo) > spaces) { /* delete extras */
  168.         result = *wo - spo - spaces;
  169.         ldelete( result, FALSE);
  170.         result = - result;
  171.     } else { /* pad with spaces */
  172.         result = spaces - (*wo - spo);
  173.         linsert( result, ' ');
  174.     }
  175.     *lp = curwp->w_dotp;
  176.     *wo = spo + spaces;
  177.     return( result);
  178. }
  179.  
  180. /* Get next char, word-oriented style.  If at end of line, append next
  181.  * line by replacing newline with a space.  Return EOF
  182.  * when there is nothing left.
  183.  */
  184. wgetc( clp, n)
  185. LINE **clp;
  186. int n;
  187. {
  188.     LINE *newlp;
  189.  
  190.     if( n > llength( *clp)) {
  191.     mlwrite( "Bad para fill");
  192.     return( EOF);
  193.     }
  194.     if( n == llength( *clp)) {
  195.     newlp = lforw( *clp);
  196.     if( llength( newlp) == 0) return( EOF);
  197.     curwp->w_doto = n;
  198.     ldelete( 1, FALSE);
  199.     linsert( 1, ' ');
  200.     *clp = curwp->w_dotp;
  201.     }
  202.     return( lgetc( *clp, n));
  203. }
  204.  
  205. /* Break line on spaces. Back-over whatever precedes the point on the current
  206.  * line and stop on the first space or the beginning of the line. If we
  207.  * reach the beginning of the line, do nothing.
  208.  * Otherwise, break the line at the space, eat previous spaces, and jump
  209.  * back to the end of the word.
  210.  * Returns TRUE on success, FALSE on errors.
  211.  */
  212. wrapword()
  213. {
  214.         register int wo, spo, oldo;
  215.     LINE *oldp;
  216.  
  217.         oldp = curwp->w_dotp;
  218.     oldo = curwp->w_doto;
  219.     for( spo = oldo; spo > 0; --spo) {
  220.         if( lgetc( oldp, spo) == ' ') break;
  221.     }
  222.     if( spo) wo = spo + 1; /* wo points at start of word */
  223.     else /* can't do it */
  224.         return( FALSE);
  225.     for( ; spo > 0; --spo) {
  226.         if( lgetc( oldp, spo) != ' ') break;
  227.     }
  228.     if( spo) spo = spo + 1; /* spo points at start of spaces */
  229.     else /* can't do it */
  230.         return( FALSE);
  231.  
  232.     /* delete spaces and insert new line */
  233.         curwp->w_doto = spo;
  234.         forwdel( FALSE, wo - spo);
  235.         newline( FALSE, 1);
  236.  
  237.     if( oldo > spo) /* adjust point */
  238.         curwp->w_doto = oldo - wo;
  239.  
  240.         return( TRUE);
  241. }
  242.                                 
  243. /*
  244.  * Move the cursor backward by "n" words. All of the details of motion are
  245.  * performed by the "backchar" and "forwchar" routines. Error if you try to
  246.  * move beyond the buffers.
  247.  */
  248. backword(f, n)
  249. {
  250.         if (n < 0)
  251.                 return (forwword(f, -n));
  252.         if (backchar(FALSE, 1) == FALSE)
  253.                 return (FALSE);
  254.         while (n--) {
  255.                 while (inword() == FALSE) {
  256.                         if (backchar(FALSE, 1) == FALSE)
  257.                                 return (FALSE);
  258.                 }
  259.                 while (inword() != FALSE) {
  260.                         if (backchar(FALSE, 1) == FALSE)
  261.                                 return (FALSE);
  262.                 }
  263.         }
  264.         return (forwchar(FALSE, 1));
  265. }
  266.  
  267. /*
  268.  * Move the cursor forward by the specified number of words. All of the motion
  269.  * is done by "forwchar". Error if you try and move beyond the buffer's end.
  270.  */
  271. forwword(f, n)
  272. {
  273.         if (n < 0)
  274.                 return (backword(f, -n));
  275.         while (n--) {
  276.                 while (inword() == FALSE) {
  277.                         if (forwchar(FALSE, 1) == FALSE)
  278.                                 return (FALSE);
  279.                 }
  280.                 while (inword() != FALSE) {
  281.                         if (forwchar(FALSE, 1) == FALSE)
  282.                                 return (FALSE);
  283.                 }
  284.         }
  285.         return (TRUE);
  286. }
  287.  
  288. /*
  289.  * Move the cursor forward by the specified number of words. As you move,
  290.  * convert any characters to upper case. Error if you try and move beyond the
  291.  * end of the buffer. Bound to "M-U".
  292.  */
  293. upperword(f, n)
  294. {
  295.         register int    c;
  296.  
  297.         if (n < 0)
  298.                 return (FALSE);
  299.         while (n--) {
  300.                 while (inword() == FALSE) {
  301.                         if (forwchar(FALSE, 1) == FALSE)
  302.                                 return (FALSE);
  303.                 }
  304.                 while (inword() != FALSE) {
  305.                         c = lgetc(curwp->w_dotp, curwp->w_doto);
  306.                         if (c>='a' && c<='z') {
  307.                                 c -= 'a'-'A';
  308.                                 lputc(curwp->w_dotp, curwp->w_doto, c);
  309.                                 lchange(WFHARD);
  310.                         }
  311.                         if (forwchar(FALSE, 1) == FALSE)
  312.                                 return (FALSE);
  313.                 }
  314.         }
  315.         return (TRUE);
  316. }
  317.  
  318. /*
  319.  * Move the cursor forward by the specified number of words. As you move
  320.  * convert characters to lower case. Error if you try and move over the end of
  321.  * the buffer. Bound to "M-L".
  322.  */
  323. lowerword(f, n)
  324. {
  325.         register int    c;
  326.  
  327.         if (n < 0)
  328.                 return (FALSE);
  329.         while (n--) {
  330.                 while (inword() == FALSE) {
  331.                         if (forwchar(FALSE, 1) == FALSE)
  332.                                 return (FALSE);
  333.                 }
  334.                 while (inword() != FALSE) {
  335.                         c = lgetc(curwp->w_dotp, curwp->w_doto);
  336.                         if (c>='A' && c<='Z') {
  337.                                 c += 'a'-'A';
  338.                                 lputc(curwp->w_dotp, curwp->w_doto, c);
  339.                                 lchange(WFHARD);
  340.                         }
  341.                         if (forwchar(FALSE, 1) == FALSE)
  342.                                 return (FALSE);
  343.                 }
  344.         }
  345.         return (TRUE);
  346. }
  347.  
  348. /*
  349.  * Move the cursor forward by the specified number of words. As you move
  350.  * convert the first character of the word to upper case, and subsequent
  351.  * characters to lower case. Error if you try and move past the end of the
  352.  * buffer. Bound to "M-C".
  353.  */
  354. capword(f, n)
  355. {
  356.         register int    c;
  357.  
  358.         if (n < 0)
  359.                 return (FALSE);
  360.         while (n--) {
  361.                 while (inword() == FALSE) {
  362.                         if (forwchar(FALSE, 1) == FALSE)
  363.                                 return (FALSE);
  364.                 }
  365.                 if (inword() != FALSE) {
  366.                         c = lgetc(curwp->w_dotp, curwp->w_doto);
  367.                         if (c>='a' && c<='z') {
  368.                                 c -= 'a'-'A';
  369.                                 lputc(curwp->w_dotp, curwp->w_doto, c);
  370.                                 lchange(WFHARD);
  371.                         }
  372.                         if (forwchar(FALSE, 1) == FALSE)
  373.                                 return (FALSE);
  374.                         while (inword() != FALSE) {
  375.                                 c = lgetc(curwp->w_dotp, curwp->w_doto);
  376.                                 if (c>='A' && c<='Z') {
  377.                                         c += 'a'-'A';
  378.                                         lputc(curwp->w_dotp, curwp->w_doto, c);
  379.                                         lchange(WFHARD);
  380.                                 }
  381.                                 if (forwchar(FALSE, 1) == FALSE)
  382.                                         return (FALSE);
  383.                         }
  384.                 }
  385.         }
  386.         return (TRUE);
  387. }
  388.  
  389. /*
  390.  * Kill forward by "n" words. Remember the location of dot. Move forward by
  391.  * the right number of words. Put dot back where it was and issue the kill
  392.  * command for the right number of characters. Bound to "M-D".
  393.  */
  394. delfword(f, n)
  395. {
  396.         register int    size;
  397.         register LINE   *dotp;
  398.         register int    doto;
  399.  
  400.         if (n < 0)
  401.                 return (FALSE);
  402.         dotp = curwp->w_dotp;
  403.         doto = curwp->w_doto;
  404.         size = 0;
  405.         while (n--) {
  406.                 while (inword() == FALSE) {
  407.                         if (forwchar(FALSE, 1) == FALSE)
  408.                                 return (FALSE);
  409.                         ++size;
  410.                 }
  411.                 while (inword() != FALSE) {
  412.                         if (forwchar(FALSE, 1) == FALSE)
  413.                                 return (FALSE);
  414.                         ++size;
  415.                 }
  416.         }
  417.         curwp->w_dotp = dotp;
  418.         curwp->w_doto = doto;
  419.         return (ldelete(size, TRUE));
  420. }
  421.  
  422. /*
  423.  * Kill backwards by "n" words. Move backwards by the desired number of words,
  424.  * counting the characters. When dot is finally moved to its resting place,
  425.  * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
  426.  */
  427. delbword(f, n)
  428. {
  429.         register int    size;
  430.  
  431.         if (n < 0)
  432.                 return (FALSE);
  433.         if (backchar(FALSE, 1) == FALSE)
  434.                 return (FALSE);
  435.         size = 0;
  436.         while (n--) {
  437.                 while (inword() == FALSE) {
  438.                         if (backchar(FALSE, 1) == FALSE)
  439.                                 return (FALSE);
  440.                         ++size;
  441.                 }
  442.                 while (inword() != FALSE) {
  443.                         if (backchar(FALSE, 1) == FALSE)
  444.                                 return (FALSE);
  445.                         ++size;
  446.                 }
  447.         }
  448.         if (forwchar(FALSE, 1) == FALSE)
  449.                 return (FALSE);
  450.         return (ldelete(size, TRUE));
  451. }
  452.  
  453. /*
  454.  * Return TRUE if the character at dot is a character that is considered to be
  455.  * part of a word. The word character list is hard coded. Should be setable.
  456.  */
  457. inword()
  458. {
  459.         register int    c;
  460.  
  461.         if (curwp->w_doto == llength(curwp->w_dotp))
  462.                 return (FALSE);
  463.         c = lgetc(curwp->w_dotp, curwp->w_doto);
  464.         if (c>='a' && c<='z')
  465.                 return (TRUE);
  466.         if (c>='A' && c<='Z')
  467.                 return (TRUE);
  468.         if (c>='0' && c<='9')
  469.                 return (TRUE);
  470.         if (c=='$' || c=='_')                   /* For identifiers      */
  471.                 return (TRUE);
  472.         return (FALSE);
  473. }
  474.  
  475.